#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "TwoProgressTableWidget.h"
#include "mysql.h"
#include <QDir>
#include <QInputDialog>
#include <QLabel>
#include <QMessageBox>
#include <QString>
#include <conio.h>
#include <QVBoxLayout>
#include "DeviceChannelTableWidget.h"

MainWindow* MainWindow::_instance = nullptr;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , m_pProjectManager(nullptr)
    , m_nIndex(0)
    , m_pChartMainWidget(new MainWidget(this))
{
    ui->setupUi(this);

    _instance = this;

    QWidget *p = takeCentralWidget();
    if (p)
        delete p;

    setDockNestingEnabled(true);

    //记录所有的dock指针
    m_docks.append(ui->dockWidgetProject);
    m_docks.append(ui->dockWidgetOscilloscope);
    m_docks.append(ui->dockWidgetDatabase);
    m_docks.append(ui->dockWidgetConfiguration);
    m_docks.append(ui->dockWidgetChannels);
    m_docks.append(ui->dockWidget_6);
    m_docks.append(ui->dockWidget_7);
    m_docks.append(ui->dockWidget_8);
    m_docks.append(ui->dockWidget_9);
    m_docks.append(ui->dockWidgetFlowChartEditor);

    on_DefalutLayoutAction_triggered();

    ui->dockWidgetOscilloscope->installEventFilter(this);

    // 初始化
    InitProjectDockWidget();

    // 初始化 流程编辑器
    /*CreateFlowChartEditorActions();
    CreateFlowChartEditorToolBox();
    CreateFlowChartEditorMenus();
    scene = new DiagramScene(itemMenu, ui->dockWidgetFlowChartEditor);
    scene->setSceneRect(QRectF(0, 0, 5000, 5000));

    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(toolBox);
    view = new QGraphicsView(scene);
    layout->addWidget(view);

    QWidget *widget = new QWidget;
    widget->setLayout(layout);
    ui->dockWidgetFlowChartEditor->setWidget(widget);*/

    // 系统工具栏
    CreateToolBars();

    /*wave = new MWaveView(ui->widgetOscilloscopeChart);
    wave->resize(ui->widgetOscilloscopeChart->size());

    // 定时器
    mvGetTimer = new QTimer(this);
    connect(mvGetTimer, SIGNAL(timeout()), this, SLOT(onMsGetTimeOut()));
    mvGetTimer->start(1);*/

    ui->dockWidgetOscilloscope->setWidget(m_pChartMainWidget);

    initTable();

    m_showTimer = new QTimer();
    m_showTimer->setInterval(10);

    connect(m_showTimer,&QTimer::timeout,this,&MainWindow::slotShowTimer);
}

void MainWindow::initTable() {
    tableWidget = new TwoProgressTableWidget(this);
    tableWidget->resize(800, 600);
    //设置表头颜色

    ui->dockWidgetChannels->setWidget(tableWidget);
    tableWidget->show();
    // 添加列
    tableWidget->addColumn("启用/未启用", "button", "未启用");
    tableWidget->addColumn("颜色", "color", QColor(Qt::white));
    tableWidget->addColumn("名称", "text", "0");
    tableWidget->addColumn("放大器名称", "text", "0");
    tableWidget->addColumn("量程", "text", "0");
    tableWidget->addColumn("最小值", "double", "0");
    tableWidget->addColumn("最大值", "double", "0");
    tableWidget->addColumn("测量值", "progress", QVariantMap({{"min", -100}, {"max", 100}, {"value", 0}, {"unit", "单位"}}));

    for(int i = 0;i < 8;i ++){
        DeviceChannel* deviceChannel = new DeviceChannel();

        deviceChannel->m_strChannelName = QStringLiteral("Dev1/ai") + QString::number(i,10);
        deviceChannel->m_strChannelNikeName = "通道0";
        deviceChannel->m_nChannelMode = 0;
        deviceChannel->m_strAmplifierName = "Gaussian";
        deviceChannel->m_bEnableIEPE = false;
        deviceChannel->m_dblMaximunValue = 10;
        deviceChannel->m_dblMinimunValue = -5;
        deviceChannel->m_dlbMeasureRangeMin = -20;
        deviceChannel->m_dlbMeasureRangeMax = 20;
        deviceChannel->m_nCouple = 0;
        deviceChannel->m_nInputConfiguration = 0;
        deviceChannel->m_nSampleRate = 10000;
        deviceChannel->m_nToReadSampleCount = 1000;
        deviceChannel->m_strUnit = "V";
        deviceChannel->m_bEnabled = false;
        deviceChannel->m_cColor = QColor(Qt::red);

        m_vecDeviceChannels.append(deviceChannel);
    }

    tableWidget->setRows(m_vecDeviceChannels);

    //tableWidget->setRowHidden(0, true); // 隐藏第一行

    deviceChannelTableWidget = new DeviceChannelTableWidget(this);
    deviceChannelTableWidget->resize(800, 600);
    //设置表头颜色
    ui->dockWidgetConfiguration->setWidget(deviceChannelTableWidget);
    deviceChannelTableWidget->show();
    // 创建父通道
    DeviceChannel *parentChannel = new DeviceChannel;
    parentChannel->m_strChannelName = "Parent Channel";
    parentChannel->m_strAmplifierName = "Amplifier A";
    parentChannel->m_dlbMeasureRangeMin = 0.0;
    parentChannel->m_dlbMeasureRangeMax = 10.0;
    parentChannel->m_strUnit = "V";
    parentChannel->m_nChannelMode = 1;
    parentChannel->m_cColor = Qt::red;
    // 创建子通道
    DeviceSubChannel *subChannel = new DeviceSubChannel;
    subChannel->m_strChannelName = "Sub Channel 1";
    subChannel->m_strAmplifierName = "Amplifier B";
    subChannel->m_dlbMeasureRangeMin = 0.0;
    subChannel->m_dlbMeasureRangeMax = 5.0;
    subChannel->m_strUnit = "mV";
    subChannel->m_nChannelMode = 2;
    subChannel->m_cColor = Qt::blue;
    // 添加到表格
    deviceChannelTableWidget->addDeviceChannel(parentChannel);
    deviceChannelTableWidget->addDeviceSubChannel(parentChannel, subChannel);

}

MainWindow::~MainWindow()
{
    delete ui;
}


MainWindow* MainWindow::instance(){
    return _instance;
}

void MainWindow::UpdateChannelData(int channelno,double value){
    for(int i = 0; i < 2000;i = i + 10){
        value = m_float64SampleData[channelno * 2000 + i];
        tableWidget->updateRowValue(channelno,value);
    }
}

void MainWindow::slotShowTimer(){
    m_nIndex++;
    m_nIndex %= 1000;
    for(int channelno = 0; channelno < MAX_CHANNEL_COUNT;channelno++){
        double value = m_float64SampleData[channelno * 1000 + m_nIndex];
        tableWidget->updateRowValue(channelno,value);
    }
}

void MainWindow::resizeEvent(QResizeEvent *){

}

bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
    if (event->type() == QEvent::Resize) {
        qDebug() << object;
    }
    return QObject::eventFilter(object, event);
}

void MainWindow::on_OpenFileAction_triggered()
{
    qDebug() << "OpenFileAction_triggered";

    TestNET8814Z();
}

void MainWindow::removeAllDock()
{
    for (int i = 0; i < 10; ++i) {
        removeDockWidget(m_docks[i]);
    }
}

void MainWindow::showDock(const QList<int> &index)
{
    if (index.isEmpty()) {
        for (int i = 0; i < 10; ++i) {
            m_docks[i]->show();
        }
    } else {
        foreach (int i, index) {
            m_docks[i]->show();
        }
    }
}

void MainWindow::on_DefalutLayoutAction_triggered()
{
    removeAllDock();
    addDockWidget(Qt::LeftDockWidgetArea, ui->dockWidgetProject);
    splitDockWidget(ui->dockWidgetProject, ui->dockWidgetChannels, Qt::Horizontal);
    splitDockWidget(ui->dockWidgetChannels, ui->dockWidgetDatabase, Qt::Horizontal);
    tabifyDockWidget(ui->dockWidgetChannels, ui->dockWidgetOscilloscope);
    tabifyDockWidget(ui->dockWidgetChannels, ui->dockWidgetConfiguration);
    /*splitDockWidget(ui->dockWidget_2, ui->dockWidgetProject, Qt::Vertical);
    splitDockWidget(ui->dockWidget_3, ui->dockWidget_6, Qt::Vertical);
    tabifyDockWidget(ui->dockWidget_1, ui->dockWidget_7);
    tabifyDockWidget(ui->dockWidgetProject, ui->dockWidget_8);
    tabifyDockWidget(ui->dockWidget_3, ui->dockWidget_9);
    tabifyDockWidget(ui->dockWidget_3, ui->dockWidget_10);*/
    showDock(QList<int>() << 0 << 1 << 2 << 3 << 4);


}

void MainWindow::on_FlowDesignLayoutAction_triggered()
{
    removeAllDock();
    /*addDockWidget(Qt::LeftDockWidgetArea, ui->dockWidget_1);
    splitDockWidget(ui->dockWidget_1, ui->dockWidget_2, Qt::Horizontal);
    splitDockWidget(ui->dockWidget_2, ui->dockWidget_3, Qt::Horizontal);
    splitDockWidget(ui->dockWidget_3, ui->dockWidget_4, Qt::Horizontal);
    splitDockWidget(ui->dockWidget_4, ui->dockWidgetProject, Qt::Horizontal);
    showDock(QList<int>() << 0 << 1 << 2 << 3 << 4);*/
}

void MainWindow::on_FlowRunLayouAction_triggered()
{
    removeAllDock();
    /*addDockWidget(Qt::LeftDockWidgetArea, ui->dockWidget_1);
    splitDockWidget(ui->dockWidget_1, ui->dockWidget_2, Qt::Vertical);
    splitDockWidget(ui->dockWidget_2, ui->dockWidget_3, Qt::Vertical);
    splitDockWidget(ui->dockWidget_3, ui->dockWidget_4, Qt::Vertical);
    splitDockWidget(ui->dockWidget_4, ui->dockWidgetProject, Qt::Vertical);
    showDock(QList<int>() << 0 << 1 << 2 << 3 << 4);*/
}

void MainWindow::InitProjectDockWidget()
{
    m_pProjectManager = new ProjectManager(ui->treeWidgetProject);
    m_pProjectManager->ReadXMLProjectFile("D:/a.xml");
}

void MainWindow::on_NewProjectAction_triggered()
{
    /*QString dlgTitle="新建项目";
    QString txtLabel="请输入项目名";
    QString defaultInput="新建项目.mpb";
    QLineEdit::EchoMode echoMode = QLineEdit::Normal;       // 正常文字输入

    bool flag = false;
    QString text = QInputDialog::getText(this, dlgTitle,txtLabel, echoMode,defaultInput, &flag);
    if (flag && !text.isEmpty()){

    }*/

    /*NewProjectDialog *pDlg = new NewProjectDialog();
    if (QDialog::Accepted == pDlg->exec()) {
        qDebug() << pDlg->m_strProjectname;
        qDebug() << pDlg->m_strPathname;

        QDir *folder = new QDir();
        QString strNewProjectPath = pDlg->m_strPathname + "/" + pDlg->m_strProjectname;
        bool exist = folder->exists(strNewProjectPath);
        if (exist) {
            QMessageBox::warning(this, tr("创建文件夹"), tr("文件夹已经存在！"));
        } else {
            bool ok = folder->mkpath(strNewProjectPath);

            if (ok) {
                QString strNewProjectFile = strNewProjectPath + "/" + pDlg->m_strProjectname
                                            + ".mpb";
                m_pProjectManager->CreateEmpytProjectFile(strNewProjectFile);
            } else {
                QMessageBox::warning(this, tr("创建文件夹"), tr("文件夹创建失败！"));
            }
        }
    }*/

    SampleDeviceDialog* pDlg = new SampleDeviceDialog(this);
    if (QDialog::Accepted == pDlg->exec()) {

    }

}

QWidget *MainWindow::CreateCellWidget(const QString &text, DiagramItem::DiagramType type)
{
    DiagramItem item(type, itemMenu);
    QIcon icon(item.image());

    QToolButton *button = new QToolButton;
    button->setIcon(icon);
    button->setIconSize(QSize(50, 50));
    button->setCheckable(true);
    m_ButtonGroup->addButton(button, int(type));

    QGridLayout *layout = new QGridLayout;
    layout->addWidget(button, 0, 0, Qt::AlignHCenter);
    layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter);

    QWidget *widget = new QWidget;
    widget->setLayout(layout);

    return widget;
}

void MainWindow::CreateFlowChartEditorActions()
{
    m_ToFrontAction = new QAction(QIcon(":/images/res/icon/FlowChart/bringtofront.png"),
                                  tr("Bring to &Front"),
                                  this);
    m_ToFrontAction->setShortcut(tr("Ctrl+F"));
    m_ToFrontAction->setStatusTip(tr("Bring item to front"));
}

void MainWindow::CreateFlowChartEditorToolBox()
{
    m_ButtonGroup = new QButtonGroup(ui->dockWidgetFlowChartEditor);
    m_ButtonGroup->setExclusive(false);
    QGridLayout *layout = new QGridLayout;
    layout->addWidget(CreateCellWidget(tr("Conditional"), DiagramItem::Conditional), 0, 0);
    layout->addWidget(CreateCellWidget(tr("Process"), DiagramItem::Step), 0, 1);
    layout->addWidget(CreateCellWidget(tr("Input/Output"), DiagramItem::Io), 1, 0);

    QWidget *widget = new QWidget;
    widget->setLayout(layout);

    layout->setRowStretch(3, 10);
    layout->setColumnStretch(2, 10);

    QWidget *itemWidget = new QWidget;
    itemWidget->setLayout(layout);

    // Background
    m_BackgroundButtonGroup = new QButtonGroup(ui->dockWidgetFlowChartEditor);

    QGridLayout *backgroundLayout = new QGridLayout;
    backgroundLayout
        ->addWidget(CreateBackgroundCellWidget(tr("Blue Grid"),
                                               ":/images/res/icon/FlowChart/background1.png"),
                    0,
                    0);
    backgroundLayout
        ->addWidget(CreateBackgroundCellWidget(tr("White Grid"),
                                               ":/images/res/icon/FlowChart/background2.png"),
                    0,
                    1);
    backgroundLayout
        ->addWidget(CreateBackgroundCellWidget(tr("Gray Grid"),
                                               ":/images/res/icon/FlowChart/background3.png"),
                    1,
                    0);
    backgroundLayout
        ->addWidget(CreateBackgroundCellWidget(tr("No Grid"),
                                               ":/images/res/icon/FlowChart/background4.png"),
                    1,
                    1);

    backgroundLayout->setRowStretch(2, 10);
    backgroundLayout->setColumnStretch(2, 10);

    QWidget *backgroundWidget = new QWidget;
    backgroundWidget->setLayout(backgroundLayout);
    // BPMN
    m_BPMNButtonGroup = new QButtonGroup(ui->dockWidgetFlowChartEditor);
    QGridLayout *BPMNLayout = new QGridLayout;
    BPMNLayout->addWidget(CreateBackgroundCellWidget(tr("Start"),
                                                     ":/images/res/icon/FlowChart/start.png"),
                          0,
                          0);
    BPMNLayout->addWidget(CreateBackgroundCellWidget(tr("Finish"),
                                                     ":/images/res/icon/FlowChart/finish.png"),
                          0,
                          1);
    BPMNLayout->addWidget(CreateBackgroundCellWidget(tr("User"),
                                                     ":/images/res/icon/FlowChart/user.png"),
                          1,
                          0);
    BPMNLayout->addWidget(CreateBackgroundCellWidget(tr("Calculator"),
                                                     ":/images/res/icon/FlowChart/calculator.png"),
                          1,
                          1);
    BPMNLayout->addWidget(CreateBackgroundCellWidget(tr("Excel"),
                                                     ":/images/res/icon/FlowChart/excel.png"),
                          2,
                          0);
    BPMNLayout->addWidget(CreateBackgroundCellWidget(tr("Excel"),
                                                     ":/images/res/icon/FlowChart/process.png"),
                          2,
                          1);

    BPMNLayout->setRowStretch(3, 10);
    BPMNLayout->setColumnStretch(3, 10);

    QWidget *BPMNWidget = new QWidget;
    BPMNWidget->setLayout(BPMNLayout);

    //! [22]
    toolBox = new QToolBox;
    toolBox->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Ignored));
    toolBox->setMinimumWidth(itemWidget->sizeHint().width());
    toolBox->addItem(itemWidget, tr("Basic Flowchart Shapes"));
    toolBox->addItem(backgroundWidget, tr("Backgrounds"));
    toolBox->addItem(BPMNWidget, tr("BMPN"));
}

QWidget *MainWindow::CreateBackgroundCellWidget(const QString &text, const QString &image)
{
    QToolButton *button = new QToolButton;
    button->setText(text);
    button->setIcon(QIcon(image));
    button->setIconSize(QSize(50, 50));
    button->setCheckable(true);
    m_BackgroundButtonGroup->addButton(button);

    QGridLayout *layout = new QGridLayout;
    layout->addWidget(button, 0, 0, Qt::AlignHCenter);
    layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter);

    QWidget *widget = new QWidget;
    widget->setLayout(layout);

    return widget;
}

void MainWindow::CreateFlowChartEditorMenus()
{
    itemMenu = menuBar()->addMenu(tr("&Item"));
    itemMenu->addAction(m_ToFrontAction);
}

void MainWindow::CreateToolBars()
{
    /*m_FlowChartEditToolBar = addToolBar(tr("FlowChartEditToolBar"));
    m_FlowChartEditToolBar->addAction(m_ToFrontAction);

    m_FontCombo = new QFontComboBox();

    m_FontSizeCombo = new QComboBox;
    m_FontSizeCombo->setEditable(true);
    for (int i = 8; i < 30; i = i + 2)
        m_FontSizeCombo->addItem(QString().setNum(i));
    QIntValidator *validator = new QIntValidator(2, 64, this);
    m_FontSizeCombo->setValidator(validator);

    m_FlowChartEditToolBar->addWidget(m_FontCombo);
    m_FlowChartEditToolBar->addWidget(m_FontSizeCombo);*/
}

/**
 * @brief MainWindow::TestNET8814Z
 * Art 8 通道信号采集测试程序
 */

#define ArtDAQErrChk(functionCall) if( ArtDAQFailed(error=(functionCall)) ) goto Error; else

int32 ART_CALLBACK EveryNCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData);
int32 ART_CALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData);

int MainWindow::TestNET8814Z(){

    /*********************************************/
    // ArtDAQ_ Configure Code
    /*********************************************/
    QString strDevice = QStringLiteral("Dev1");
    QString strChannelsName = "";
    for(int i = 0;i < MAX_CHANNEL_COUNT;i++){
        QString strChannelName = strDevice + "/ai" + QString::number(i);
        strChannelsName += strChannelName + ",";
    }
    QByteArray baChannelName = strChannelsName.toLatin1();

    ArtDAQ_CreateTask("",&m_hTaskHandle);
    ArtDAQ_CreateAIVoltageChan(m_hTaskHandle,baChannelName.data(),"",ArtDAQ_Val_Cfg_Default,-10.0,10.0,ArtDAQ_Val_Volts,NULL);
    ArtDAQ_CfgSampClkTiming(m_hTaskHandle,"",1000.0,ArtDAQ_Val_Rising,ArtDAQ_Val_ContSamps,1000);

    ArtDAQ_RegisterEveryNSamplesEvent(m_hTaskHandle,ArtDAQ_Val_Acquired_Into_Buffer,1000,0,EveryNCallback,m_float64SampleData);
    ArtDAQ_RegisterDoneEvent(m_hTaskHandle,0,DoneCallback,NULL);

    return 0;
}

int32 ART_CALLBACK EveryNCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData)
{
    int32       error=0;
    char        errBuff[2048]={'\0'};
    static int  totalRead=0;
    int32       read=0;
    //float64     data[2000];

    /*********************************************/
    // ArtDAQ_ Read Code
    /*********************************************/
    ArtDAQErrChk (ArtDAQ_ReadAnalogF64(taskHandle,1000,10.0,ArtDAQ_Val_GroupByChannel/*ArtDAQ_Val_GroupByScanNumber*/,
                                      (float64*)callbackData,8 * 1000,&read,NULL));
    if( read > 0 ) {
        MainWindow::SendDataMessage();
        qDebug() << ("Acquired %d samples. Total %d\r",(int)read,(int)(totalRead+=read));
        fflush(stdout);
    }

Error:
    if( ArtDAQFailed(error) ) {
        ArtDAQ_GetExtendedErrorInfo(errBuff,2048);
        /*********************************************/
        // ArtDAQ_ Stop Code
        /*********************************************/
        ArtDAQ_StopTask(taskHandle);
        ArtDAQ_ClearTask(taskHandle);
        qDebug() << ("ArtDAQ_ Error: %s\n",errBuff);
    }
    return 0;
}

int32 ART_CALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData)
{
    int32   error=0;
    char    errBuff[2048]={'\0'};

    // Check to see if an error stopped the task.
    ArtDAQErrChk (status);

Error:
    if( ArtDAQFailed(error) ) {
        ArtDAQ_GetExtendedErrorInfo(errBuff,2048);
        ArtDAQ_ClearTask(taskHandle);
        qDebug() << ("ArtDAQ Error: %s\n",errBuff);
    }
    return 0;
}

/**
 * @brief MainWindow::on_EditChartaction_triggered
 * MySQL
 */
void MainWindow::on_EditChartaction_triggered()
{

    MySql db;

    //1 测试查询金条
    QList<QHash<QString, QVariant>>  r=db.select("*","user","1=1");
    qDebug()<<"测试查询";
    qDebug()<<"count:"<<r.size();
    qDebug()<<r;

    //1 查询1条
    // db.find("user","id=1");

    //2测试插入
    qDebug()<<"测试插入";
    QHash<QString, QVariant> uobj;
    uobj.insert("name","aaa");
    uobj.insert("id","222");
    auto r2=db.insert("user", uobj);
    qDebug()<<"操作:"<<r2;


    //3测试批量插入=========================
    qint64 CurrentMEpoch1 = QDateTime::currentMSecsSinceEpoch();
    // 准备批量插入的数据
    QString tableName = "user";
    QStringList columns = {"name", "id"};
    db.del("user","1=1");
    QList<QList<QVariant>> dataList = {
    };
    for(int i=0;i<1000;++i){
        dataList.push_back({"a",i});
    }
    // 执行批量插入
    if (db.batchInsert(tableName, columns, dataList)) {
        qDebug() << "Batch insert successful!,操作成功";
    } else {
        qDebug() << "Batch insert failed:" << db.lastError();
    }
    qint64 CurrentMEpoch2 = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "批量插入，耗时：" << QString::number(CurrentMEpoch2 - CurrentMEpoch1) << "毫秒";
    // end===============================
}

/**
 * @brief MainWindow::on_EditChart2Action_triggered
 * Influx
 */
void MainWindow::on_EditChart2Action_triggered()
{
    ArtDAQ_StartTask(m_hTaskHandle);
    //启动定时器
    m_showTimer->start();
}

/**
 * @brief MainWindow::on_EditChart3Action_triggered
 * IOTDB
 */
void MainWindow::on_EditChart3Action_triggered()
{
    ArtDAQ_StopTask(m_hTaskHandle);
    ArtDAQ_ClearTask(m_hTaskHandle);
    //启动定时器
    m_showTimer->stop();
}

